#pragma once

#include <iostream>
#include <string>
#include <atomic>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include "log.hpp"
//工具类

class Util_Time {
    public:
        static std::string GetMillSecTime()//获取毫秒级时间
        {
            struct timeval tv;
            gettimeofday(&tv, NULL);
            long long int time_us = tv.tv_sec * 1000 + tv.tv_usec/1000;
            return std::to_string(time_us);
        }
};

class Util_File {
        static const std::string default_path ;//默认路径
    public:

        //形成特定文件名
        static std::string UniqueFileName()
        {
            static std::atomic_uint count(0); // 静态原子计数器
            uint32_t current_count = count.fetch_add(1, std::memory_order_relaxed);//原子计数器自增,返回旧值
            
            // 直接构造返回，避免临时string的拷贝
            return Util_Time::GetMillSecTime() + "_" + std::to_string(current_count);
        }
        //写文件
        static bool WriteFile(const std::string& filename, const std::string& content)
        {
            std::ofstream ofs(filename);//打开文件
            if(!ofs.is_open()){
                LOG__ERR("open file failed");
                return false;
            }
            ofs<<content;//写入内容
            ofs.close();
            return true;
        }
        //读文件
        static bool ReadFile(const std::string& filename, std::string *content,bool keep_line_break = false)
        {
            std::ifstream ifs(filename);//打开文件
            if(!ifs.is_open()){
                LOG__ERR("open file failed");
                return false;
            }
            std::string line;
            while(std::getline(ifs, line)){//读取每行内容
                if(keep_line_break){
                    *content += line + "\n";
                }else{
                    *content += line;
                }
            }
            ifs.close();
            return true;
        }

        //添加后缀
        static std::string AddSuffix(const std::string& filename, const std::string& suffix)
        {
            std::string file = "" ; 
            file += default_path;
            file += filename;
            file += suffix;
            return file;
        }
        
        //获取源文件扩展名
        static std::string ExtensionSrc(const std::string& filename)
        {
            return AddSuffix(filename, ".cpp");
        }

        //获取目标文件（可执行程序）扩展名
        static std::string ExtensionObj(const std::string& filename)
        {
            return AddSuffix(filename, ".exe");
        }

        //获取(编译时)错误文件扩展名
        static std::string ExtCompError(const std::string& filename)
        {
            return AddSuffix(filename, ".compile_err");
        }

        //判断文件是否存在
        static bool IsFileExist(const std::string& filename)
        {
            struct stat stbuffer;
            int ret = stat(filename.c_str(), &stbuffer);
            if(ret == 0){//获取文件属性成功
                return true;
            }else{//获取文件属性失败
                // LOG__ERR(" stat failed");
                return false;
            }
            return false;
        }

        //运行时重定向3个流的文件
        //1.标准输入stdin
        static std::string Stdindup(const std::string& filename)
        {
            return AddSuffix(filename, ".stdin");
        }
        //2.标准输出stdout
        static std::string Stdoutdup(const std::string& filename)
        {
            return AddSuffix(filename, ".stdout");
        }
        //3.标准错误stderr
        static std::string Stderrdup(const std::string& filename)
        {
            return AddSuffix(filename, ".stderr");
        }


};
const std::string Util_File::default_path = "/home/dyx/Oline_judge/compile_server/temp_file/";//默认路径



class Util_String {
    public:
        //分割字符串
        static void SplitStr(const std::string &str,std::vector<std::string> *out,const std::string &sep)
        {
            int start = 0;
            int end = 0;
            while(start>=0 && start<str.size()){
                end = str.find(sep, start);
                if(end != std::string::npos){
                    if(end == start){
                        start = end + sep.size();
                        continue;
                    }
                    out->push_back(str.substr(start, end - start));
                    start = end + sep.size();
                }else{
                    out->push_back(str.substr(start));
                    break;
                }

            }    
        
        }
};